﻿using System;

namespace KeyWordSearch.ProcessTree
{
	/// <summary>
	/// 特化されまくってるので他の場所で使おうとか思わない方が幸せ。
	/// </summary>
	/// <typeparam name="T">ほぼ一択でのーどｗ</typeparam>
	internal class InnerList<T> where T :class
	{
		private class InnerListElement<U> where U:class
		{
			public InnerListElement(U value)
			{
				this.Value = value;
				this.Next = null;
				this.Previous = null;
			}

			public U Value
			{
				get;
				private set;
			}

			public InnerListElement<U> Next
			{
				get;
				set;
			}

			public InnerListElement<U> Previous
			{
				get;
				set;
			}
		}

		private InnerListElement<T> Head_;
		private bool IsReset_;
		private bool IsChanged_;
		private InnerListElement<T> Current_;

		public InnerList()
		{
			Head_=null;
			IsReset_=true;
			IsChanged_ = false;
			Current_ = null;
		}

		public void Add(T Value)
		{
			var tmp = Head_;
			Head_ = new InnerListElement<T>(Value);

			if (tmp != null)
			{
				Head_.Next = tmp;
				tmp.Previous = Head_;
			}

			Count++;
			IsChanged_ = true;
		}

		public int Count
		{
			get;
			private set;
		}

		public T Current
		{
			get
			{
				if (Current_ == null)
				{
					return null;
				}
				else
				{
					return Current_.Value;
				}
			}
		}

		public void MoveCurrentToHead()
		{
			if (Current_ == null || IsReset_)
			{
				return;
			}

			if (Current_ != Head_)
			{
				var Next = Current_.Next;
				var Previous = Current_.Previous;

				if (Next != null)
				{
					Next.Previous = Previous;
				}

				if (Previous != null)
				{
					Previous.Next = Next;
				}

				Head_.Previous = Current_;
				Current_.Previous = null;
				Current_.Next = Head_;
				Head_ = Current_;

				IsChanged_ = true;
			}

		}



		public void Reset()
		{
			IsReset_ = true;

			Current_ = new InnerListElement<T>(null);
			Current_.Previous = null;
			Current_.Next = Head_;

			IsChanged_ = false;
		}

		public bool Next()
		{
			IsReset_ = false;

			if (!IsChanged_)
			{
				if (Current_ != null)
				{
					Current_ = Current_.Next;
				}

				if (Current_ == null)
				{
					return false;
				}
				else
				{
					return true;
				}
			}
			else
			{
				throw new InvalidOperationException();
			}

		}
	}

	
}

